﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Net.Http;
using System.Web;
using Eagles.Base;
using Eagles.Base.Md5Helper;
using Eagles.DomainService.Model.Sms;
using Eagles.DomainService.Model.User;
using Eagles.DomainService.Core.Utility;
using Eagles.Interface.Core.User;
using Eagles.Interface.Configuration;
using Eagles.Interface.DataAccess.Util;
using Eagles.Interface.DataAccess.UserInfo;
using Eagles.Application.Model;
using Eagles.Application.Model.Common;
using Eagles.Application.Model.User.Login;
using Eagles.Application.Model.User.Register;
using Eagles.Application.Model.User.EditUser;
using Eagles.Application.Model.User.ForgetPwd;
using Eagles.Application.Model.User.BranchUser;
using Eagles.Application.Model.User.EditUserCollectLog;
using Eagles.Application.Model.User.EditUserPwd;
using Eagles.Application.Model.User.EditUserNoticeIsRead;
using Eagles.Application.Model.User.GetUserCollectLog;
using Eagles.Application.Model.User.GetUserCollectLogExists;
using Eagles.Application.Model.User.GetUserInfo;
using Eagles.Application.Model.User.GetUserNotice;
using Eagles.Application.Model.User.GetUserRelationship;

namespace Eagles.DomainService.Core.User
{
    public class UserHandler : IUserHandler
    {
        private readonly IUserInfoAccess userInfoAccess;
        private readonly IUtil util;
        private readonly IMd5Helper md5Helper;
        private readonly IEaglesConfig configuration;

        public UserHandler(IUserInfoAccess userInfoAccess, IUtil util, IMd5Helper md5Helper, IEaglesConfig configuration)
        {
            this.md5Helper = md5Helper;
            this.userInfoAccess = userInfoAccess;
            this.util = util;
            this.configuration = configuration;
        }

        public EditUserResponse EditUser(EditUserRequest request)
        {
            var response = new EditUserResponse();
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            var reqUserInfo = request.RequestUserInfo;
            var userInfo = new TbUserInfo()
            {
                UserId = tokens.UserId,
                PhotoUrl = reqUserInfo.PhotoUrl,
                Name = reqUserInfo.Name,
                Sex = reqUserInfo.Gender,
                Marital = reqUserInfo.Marital,
                Birthday = reqUserInfo.Birth,
                Address = reqUserInfo.Address,
                OriginAddress = reqUserInfo.OriginAddress,
                Ethnic = reqUserInfo.Ethnic,
                Dept = reqUserInfo.Department,
                Company = reqUserInfo.Employer,
                Origin = reqUserInfo.Origin
            };
            var result = userInfoAccess.EditUser(userInfo);
            if (result <= 0)
                throw new TransactionException(MessageCode.NoData, MessageKey.NoData);
            return response;
        }

        public EditUserPwdResponse EditUserPwd(EditUserPwdRequest request)
        {
            var response = new EditUserPwdResponse();
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            var result = userInfoAccess.GetLogin(request.AppId, request.Phone);
            if (result == null)
                throw new TransactionException(MessageCode.UserNotExists, MessageKey.UserNotExists);
            var password = md5Helper.Md5Encypt(request.UserPwd);
            if (!result.Password.Equals(password))
                throw new TransactionException(MessageCode.OriginalPasswordError, MessageKey.OriginalPasswordError);
            var newPwd = md5Helper.Md5Encypt(request.NewPwd);
            var userInfo = new TbUserInfo()
            {
                Phone = request.Phone,
                Password = newPwd
            };
            userInfoAccess.EditUserPwd(userInfo);
            return response;
        }

        public ForgetPwdResponse ForgetPwd(ForgetPwdRequest request)
        {
            var response = new ForgetPwdResponse();
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (string.IsNullOrEmpty(request.Phone) || request.Phone.Length != 11 || string.IsNullOrEmpty(request.NewPwd))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var login = userInfoAccess.GetLogin(request.AppId, request.Phone);
            if (login == null)
                throw new TransactionException(MessageCode.NotExistsPhone, MessageKey.NotExistsPhone);
            //验证短信验证码
            var codeInfo = new TbValidCode() { Phone = request.Phone, ValidCode = request.ValidCode, Seq = request.Seq };
            var resultCode = userInfoAccess.GetValidCode(codeInfo);
            if (resultCode == null)
                throw new TransactionException(MessageCode.InvalidCode, MessageKey.InvalidCode);
            if (resultCode.ExpireTime < DateTime.Now)
                throw new TransactionException(MessageCode.ExpireValidateCode, MessageKey.ExpireValidateCode);
            var newPwd = md5Helper.Md5Encypt(request.NewPwd);
            var userInfo = new TbUserInfo()
            {
                Phone = request.Phone,
                Password = newPwd
            };
            userInfoAccess.EditUserPwd(userInfo);
            return response;
        }

        public EditUserCollectLogResponse EditUserCollectLog(EditUserCollectLogRequest request)
        {
            var response = new EditUserCollectLogResponse();
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            var userCollectLogInfo = userInfoAccess.GetUserCollectLog(request.CollectType, request.NewsId, tokens.UserId);
            if (request.Status == "0")
            {
                //如果已收藏/点赞 并且 Status=0 报错
                if (userCollectLogInfo != null && userCollectLogInfo.Status == "0")
                    throw new TransactionException(MessageCode.UserCollectLogExists, MessageKey.UserCollectLogExists);
                //如果已收藏/点赞 并且 Status=1 重新收藏/点赞
                if (userCollectLogInfo != null && userCollectLogInfo.Status == "1")
                {
                    var userCollectLog = new TbUserCollectLog()
                    {
                        CollectType = request.CollectType,
                        UserId = tokens.UserId,
                        NewsId = request.NewsId,
                        Status = "0"
                    };
                    userInfoAccess.EditUserCollectLog("1", userCollectLog);
                }
                else if (userCollectLogInfo == null)
                {
                    //如果已收藏/点赞 并且 Status=1 取消收藏
                    var userCollectLog = new TbUserCollectLog()
                    {
                        CollectType = request.CollectType,
                        OrgId = tokens.OrgId,
                        BranchId = tokens.BranchId,
                        UserId = tokens.UserId,
                        NewsId = request.NewsId,
                        NewsType = request.NewsType,
                        NewsTitle = request.Title,
                        NewsUrl = request.NewsUrl,
                        NewsImage = request.ImageUrl,
                        CreateDate = DateTime.Now,
                        Author = request.Author,
                        Status = "0"
                    };
                    //新增收藏
                    userInfoAccess.EditUserCollectLog("0", userCollectLog);
                }
            }
            else
            {
                if(userCollectLogInfo == null)
                    throw new TransactionException(MessageCode.UserCollectLogNotExists, MessageKey.UserCollectLogNotExists);
                var userCollectLog = new TbUserCollectLog()
                {
                    CollectType = request.CollectType,
                    UserId = tokens.UserId,
                    NewsId = request.NewsId,
                    Status = "1"
                };
                //取消收藏
                userInfoAccess.EditUserCollectLog("1", userCollectLog);
            }
            return response;
        }

        public LoginResponse Login(LoginRequest request)
        {
            var response = new LoginResponse();
            var expireTime = DateTime.Now;
            var tokenExp = configuration.EaglesConfiguration.TokenExpTime;
            var rememberTokenExp = configuration.EaglesConfiguration.RememberTokenExpTime;
            var now = DateTime.Now;
            if (request.IsRememberPwd == 0)
                expireTime = now.AddMinutes(tokenExp);
            else
                expireTime = now.AddMinutes(rememberTokenExp);
            var guid = Guid.NewGuid().ToString("N");
            var result = userInfoAccess.GetLogin(request.AppId, request.Phone);
            if (result == null)
                throw new TransactionException(MessageCode.UserNotExists, MessageKey.UserNotExists);
            if (result.IsCustomer == 1 && result.OrgId != request.AppId)
                throw new TransactionException(MessageCode.UserNotExists, MessageKey.UserNotExists);
            //登录城市
            var ip = HttpContext.Current.Request.UserHostAddress;
            var ipCity = IpAddress.GetIpCitys(ip);
            var loginCity = result.LoginCity;
            TbValidCode resultCode;
            if (request.ValidCode > 0)
            {
                var codeInfo = new TbValidCode() { Phone = request.Phone, ValidCode = request.ValidCode, Seq = request.Seq };
                resultCode = userInfoAccess.GetValidCode(codeInfo);
                if (resultCode == null)
                    throw new TransactionException(MessageCode.InvalidCode, MessageKey.InvalidCode);
            }
            else
            {
                if (!string.IsNullOrEmpty(ipCity) && !string.IsNullOrEmpty(loginCity) && ipCity != loginCity)
                    throw new TransactionException(MessageCode.LoginCityError, MessageKey.LoginCityError);
            }
            //更新登录城市
            if (!string.IsNullOrEmpty(ipCity) && ipCity != loginCity)
            {
                var userInfo = new TbUserInfo()
                {
                    Phone = request.Phone,
                    LoginCity = ipCity
                };
                userInfoAccess.EditUserCity(userInfo);
            }
            var password = md5Helper.Md5Encypt(request.UserPwd);
            if (!result.Password.Equals(password))
                throw new TransactionException(MessageCode.UserNameOrPasswordError, MessageKey.UserNameOrPasswordError);
            //登录新增Token
            var userToken = new TbUserToken()
            {
                OrgId = result.OrgId,
                BranchId = result.BranchId,
                UserId = result.UserId,
                Token = guid,
                CreateTime = now,
                ExpireTime = expireTime,
                TokenType = 0
            };
            userInfoAccess.UpdateToken(userToken); //勿删，登出其他登录用户
            var tokenInfo = userInfoAccess.InsertToken(userToken);
            if (tokenInfo >= 1)
                response.Token = guid;
            else
                throw new TransactionException(MessageCode.LoginFail, MessageKey.LoginFail);
            response.UserId = result.UserId;
            response.IsInternalUser = result.IsCustomer;
            response.TokenExpTime = expireTime.ToString("yyyy-MM-dd HH:mm:ss");
            return response;
        }

        public RegisterResponse Register(RegisterRequest request)
        {
            var response = new RegisterResponse();
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (string.IsNullOrEmpty(request.Phone) || request.Phone.Length != 11 || string.IsNullOrEmpty(request.UserPwd))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var login = userInfoAccess.GetLogin(request.AppId, request.Phone);
            if (login != null)
                throw new TransactionException(MessageCode.ExistsPhone, MessageKey.ExistsPhone);
            var userInfo = new TbUserInfo()
            {
                OrgId = request.AppId,
                Name = request.Phone.MaskPhone(),
                Phone = request.Phone,
                Password = md5Helper.Md5Encypt(request.UserPwd),
                CreateTime = DateTime.Now,
                IsCustomer = 0,
                BranchId = 0,
                Score = 0,
                EditTime = DateTime.Now,
                Status = 0
                //IsLeader = 0,
            };
            var codeInfo = new TbValidCode() { Phone = request.Phone, ValidCode = request.ValidCode, Seq = request.Seq };
            var resultCode = userInfoAccess.GetValidCode(codeInfo);
            if (resultCode == null)
                throw new TransactionException(MessageCode.InvalidCode, MessageKey.InvalidCode);
            if (resultCode.ExpireTime < DateTime.Now)
                throw new TransactionException(MessageCode.ExpireValidateCode, MessageKey.ExpireValidateCode);
            var result = userInfoAccess.CreateUser(userInfo);
            return response;
        }

        public EditUserNoticeIsReadResponse EditUserNoticeIsRead(EditUserNoticeIsReadRequest request)
        {
            var response = new EditUserNoticeIsReadResponse();
            if (request.NewsId < 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var result = userInfoAccess.EditUserNoticeIsRead(request.NewsId);
            if (result <= 0)
                return response;
            else
                throw new TransactionException(MessageCode.SystemError, MessageKey.SystemError);
        }

        public GetUserInfoResponse GetUserInfo(GetUserInfoRequest request)
        {
            var response = new GetUserInfoResponse();
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var result = userInfoAccess.GetUserInfo(tokens.UserId);
            if (result == null)
                throw new TransactionException(MessageCode.NoData, MessageKey.NoData);
            //可参加活动数量
            var activityCount = userInfoAccess.GetActivityCount(tokens.UserId, tokens.BranchId);
            //负责任务的数量
            var taskCount = userInfoAccess.GetTaskCount(tokens.UserId);
            var userInfo = new ResUser
            {
                UserId = result.UserId,
                Name = result.Name,
                Gender = result.Sex,
                Marital = result.Marital,
                Birth = result.Birthday.ToString("yyyy-MM-dd"),
                Telphone = result.Phone,
                Address = result.Address,
                Origin = result.Origin,
                OriginAddress = result.OriginAddress,
                Ethnic = result.Ethnic,
                Branch = result.BranchName,
                Department = result.Dept,
                Education = result.Education,
                School = result.School,
                IdCard = result.IdNumber,
                Employer = result.Company,
                PrepPartyDate = result.PreMemberTime.ToString("yyyy-MM-dd"),
                FormalPartyDat = result.MemberTime.ToString("yyyy-MM-dd"),
                PartyType = result.MemberType == 0 ? "党员" : "预备党员",
                Provice = result.Provice,
                City = result.City,
                District = result.District,
                PhotoUrl = result.PhotoUrl,
                Score = result.Score,
                MyOrganization = result.OrgName
            };
            response.ResultUserInfo = userInfo;
            response.ActivityCount = activityCount;
            response.TaskCount = taskCount;
            return response;
        }

        public GetUserNoticeResponse GetUserNotice(GetUserNoticeRequest request)
        {
            var response = new GetUserNoticeResponse();
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidParameter);
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var result = userInfoAccess.GetUserNotice(tokens.UserId, request.AppId, request.PageIndex, request.PageSize);
            if (result != null && result.Count > 0)
            {
                response.NoticeList = result?.Select(x => new UserNotice
                {
                    NewsId = x.NewsId,
                    Title = x.Title,
                    Content = x.Content,
                    IsRead = x.IsRead,
                    CreateTime = x.CreateTime.ToString("yyyy-MM-dd HH:mm"),
                    UserId = x.UserId,
                    FromUser = x.FromUser,
                    TargetUrl = x.TargetUrl
                }).ToList();
            }
            else
                throw new TransactionException(MessageCode.NoData, MessageKey.NoData);
            return response;
        }

        public GetUserRelationshipResponse GetUserRelationship(GetUserRelationshipRequest request)
        {
            var response = new GetUserRelationshipResponse();
            var userRelationship = new List<UserRelationship>();
            var userId = request.UserId;
            if (request.Type == 2)
            {
                //查询下级
                var superiorUserList = userInfoAccess.GetRelationship(userId, false);
                superiorUserList.ForEach(x =>
                {
                    userRelationship.Add(new UserRelationship()
                    {
                        UserId = x.UserId,
                        Name = x.Name,
                        IsLeader = false,
                        ImgUrl = x.PhotoUrl,
                        TaskCount = x.TaskCount
                    });
                });
                response.UserList = userRelationship;
                return response;
            }
            //其他
            var userInfo = userInfoAccess.GetOrgUser(request.AppId);
            response.UserList = userInfo?.Select(x => new UserRelationship()
            {
                UserId = x.UserId,
                BranchName = x.BranchName,
                Name = x.Name,
                ImgUrl = x.PhotoUrl,
                TaskCount = x.TaskCount
            }).ToList();
            return response;
        }

        public GetBranchUserResponse GetBranchUser(GetBranchUserRequest request)
        {
            if (string.IsNullOrEmpty(request.Token))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var userInfo = util.GetUserId(request.Token, 0);
            if (userInfo == null)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            var branchId = userInfo.BranchId;
            var result = userInfoAccess.GetBranchUser(request.AppId, branchId, request.Name);
            var branchUser = result.Select(x => new BranchUser()
            {
                UserId = x.UserId,
                UserName = x.Name,
                BranchName = x.BranchName,
                OrgName = x.OrgName
            }).ToList();
            return new GetBranchUserResponse()
            {
                BranchUsers = branchUser
            };
        }

        public GetUserCollectLogResponse GetUserCollectLog(GetUserCollectLogRequest request)
        {
            var response = new GetUserCollectLogResponse();
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            var result = userInfoAccess.GeUserCollectLog(request.CollectType, tokens.OrgId, tokens.BranchId, tokens.UserId);
            if (result != null && result.Count > 0)
            {
                response.CollectsList = result?.Select(x => new UserCollect
                {
                    NewsId = x.NewsId,
                    Title = x.NewsTitle,
                    NewsType = x.NewsType,
                    ImageUrl = x.NewsImage,
                    NewsUrl = x.NewsUrl,
                    CreateDate = x.CreateDate.ToString("yyyy-MM-dd HH:mm"),
                    Status = x.Status,
                    Author = x.Author
                }).ToList();
            }
            else
                throw new TransactionException(MessageCode.NoData, MessageKey.NoData);
            return response;
        }

        public GetUserCollectLogExistsResponse GetUserCollectLogExists(GetUserCollectLogExistsRequest request)
        {
            var response = new GetUserCollectLogExistsResponse();
            if (request.AppId <= 0)
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            if (!util.CheckAppId(request.AppId))
                throw new TransactionException(MessageCode.InvalidParameter, MessageKey.InvalidParameter);
            var tokens = util.GetUserId(request.Token, 0);
            if (tokens == null || tokens.UserId <= 0)
                throw new TransactionException(MessageCode.InvalidToken, MessageKey.InvalidToken);
            var userCollectLogInfo = userInfoAccess.GetUserCollectLog(request.CollectType, request.NewsId, tokens.UserId);
            if (userCollectLogInfo != null && userCollectLogInfo.Status == "0")
                response.UserCollectsLog = true;
            else
                response.UserCollectsLog = false;
            return response;
        }
    }
}